from docx import Document
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
from PyQt5.QtGui import *
import sys

# 定义命名空间,用于xml的node
namespaces = {
    "w": "http://schemas.openxmlformats.org/wordprocessingml/2006/main"
}

"""
reverse_find 
反向查找

s = "abcdefghijk"
print(reverse_find(s, "c", 5))  # 输出 2（从位置5向左找到'c'在索引2）
print(reverse_find(s, "efg", 8))  # 输出 4（'efg'在索引4-6）
print(reverse_find(s, "xyz", 10))  # 输出 -1（未找到）
"""
def reverse_find(s, sub, start_pos):
    """
    从指定位置向左查找子串最后一次出现的位置
    :param s: 原字符串
    :param sub: 要查找的子串
    :param start_pos: 开始查找的位置（包含该位置）
    :return: 子串在原字符串中的索引（从左到右），未找到返回 -1
    """
    # 截取从开头到 start_pos 的子串（包含 start_pos 位置的字符）
    sliced = s[:start_pos]
    # 反向查找子串
    index_in_slice = sliced.rfind(sub)
    if index_in_slice == -1:
        return -1
    # 转换为原字符串的索引
    return index_in_slice

"""
getValueIndocx
在docx text里 查找关键字

#| 	入库单号 | 	20231206-007  |
#key=入库单号
#return=20231206-007
"""
def getValueIndocx(key : str, docx_text : str)->str:
    try:
        idx0 = 0
        while True:
            idx1 = docx_text.index(key, idx0) + len(key)    #匹配关键字
            # idx4 = reverse_find(docx_text, '|', idx1) + 1   #匹配关键字的开始字符
            idx4 = max([reverse_find(docx_text, '：', idx1), reverse_find(docx_text, '|', idx1)]) + 1    #匹配关键字的开始字符
            idx1 = min([docx_text.find('：', idx1), docx_text.find('|', idx1)]) #匹配关键字的结束字符

            idx2 = idx1 + 1                             #结束字符
            idx3 = docx_text.index('|', idx2)           #结束字符的下一个边界，即key对于的value
            # print(key, 'idx4:', idx4, 'idx1:', idx1, 'text:', text[idx4: idx1].strip(),  'key:', key, 'search result:', text[idx2: idx3].strip())
            # print(text[idx4: idx1].strip() , 'key: ', key)
            if text[idx4: idx1].strip() == key: #key完全匹配
                break
            idx0 = idx1
    except Exception as re:
        print(re, key)
        return ''

    # print(key, 'search result:', text[idx2: idx3].strip())
    return text[idx2: idx3].strip()

"""
readdocx
将docx转成文本,仅支持一个table的docx
"""
def readdocx(docx_file):
    doc = Document(docx_file)
    text = docx_file + '\n\n'
    # 读取表格
    for table in doc.tables:
        element = table._element
        nodes = element.xpath("//w:sym | //w:t | //w:tr | //w:tc | //w:p")
        for node in nodes:
            #<w:sym w:font="Wingdings" w:char="F0A8"/>
            if node.tag.endswith("sym"): #符号
                # 处理符号节点
                char_code = node.get("{%s}char" % namespaces["w"])
                font_code = node.get("{%s}font" % namespaces["w"])
                if char_code in ['0052', 'F0FE', '00FE', 'F052']:
                    text += '☑'
                if char_code in ['00A8', '00A3', 'F0A8']:
                    text += '☐'  
            if node.tag.endswith("t"): #text
                text += node.text
            if node.tag.endswith("p"): #段落
                text += '\t'
            if node.tag.endswith("tc"): #表格分割
                text += ' | '
            if node.tag.endswith("tr"): #表格分割
                text += '\n'
    return text

if __name__ == "__main__":
    app = QApplication([])
    textEdit = QTextEdit()

    #入库单
    docx_file_list = [
          "C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_插件化模型弹视频插件/入库单/安防_插件化模型弹视频插件V1.0.2.20250411 - 入库单.docx"
        , "C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_历史告警视频模块/入库单/安防_历史告警视频模块V1.0.1.20250411 - 入库单.docx"
        , "C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_历史视频模块/入库单/安防_历史视频模块V1.0.1.20250411 - 入库单.docx"
        , "C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_实时视频监控插件/入库单/安防_实时视频监控插件V1.0.1.20250411 - 入库单.docx"
        , "C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_实时视频监控模块/入库单/安防_实时视频监控模块V1.0.1.20250411 - 入库单.docx"
        , "C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_视频联动插件/入库单/安防_视频联动插件V1.0.2.20250411 - 入库单.docx"
        , "C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/可视化接地视频插件/入库单/可视化接地视频插件V1.1.1.20250411 - 入库单.docx"
        , "C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/实时视频监控插件/入库单/实时视频监控插件V1.0.2.20250411 - 入库单.docx"
        , "C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/实时视频监控模块/入库单/实时视频监控模块V1.0.2.20250411 - 入库单.docx"
    ]
    
    horizontalLabels = [
        '入库的原因', '入库单号', '申请时间', '编译环境要求', '是否需要发布', 
        '软件名称/标识', '版本', '入库路径', 'svn中的版本号Revision', '版本号',
        '软件更改报告单', 'Bin（需要发布）', 'doc（需要发布）', 'Bin', 'doc', 
        'src', '入库检查项'
        ]
    verticalLabels = [file.split('/')[-1:][0] for file in docx_file_list]

    #软件更改报告单
    docx_file_list = [
        'C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_插件化模型弹视频插件/入库单/安防_插件化模型弹视频插件V1.0.2.20250411 - 软件更改报告单.docx'
        ,'C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_历史告警视频模块/入库单/安防_历史告警视频模块V1.0.1.20250411 - 软件更改报告单.docx'
        ,'C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_历史视频模块/入库单/安防_历史视频模块V1.0.1.20250411 - 软件更改报告单.docx'
        ,'C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_实时视频监控插件/入库单/安防_实时视频监控插件V1.0.1.20250411 - 软件更改报告单.docx'
        ,'C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_实时视频监控模块/入库单/安防_实时视频监控模块V1.0.1.20250411 - 软件更改报告单.docx'
        ,'C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/安防_视频联动插件/入库单/安防_视频联动插件V1.0.2.20250411 - 软件更改报告单.docx'
        ,'C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/可视化接地视频插件/入库单/可视化接地视频插件V1.1.1.20250411 - 软件更改报告单.docx'
        ,'C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/实时视频监控插件/入库单/实时视频监控插件V1.0.2.20250411 - 软件更改报告单.docx'
        ,'C:/Users/ch593/Documents/SVN/轨道交通_综合监控_南京地铁6号线_2023/2-软件模块/实时视频监控模块/入库单/实时视频监控模块V1.0.2.20250411 - 软件更改报告单.docx'
    ]
    horizontalLabels = [
        '原版本号', '修改后的版本号', '更改日期', '所属系统', '软件名称',
        '更改人', '更改'
    ]
    verticalLabels = [file.split('/')[-1:][0] for file in docx_file_list]

    tableWidget = QTableWidget()
    tableWidget.setRowCount(len(verticalLabels))
    tableWidget.setColumnCount(len(horizontalLabels))
    tableWidget.horizontalHeader().setDefaultSectionSize(200)
    tableWidget.setVerticalHeaderLabels(verticalLabels)
    tableWidget.setHorizontalHeaderLabels(horizontalLabels)
    tableWidget.horizontalHeader().sectionDoubleClicked.connect(lambda index: tableWidget.resizeColumnToContents(index))

    for row, docx_file in enumerate(docx_file_list):
        text = readdocx(docx_file)
        textEdit.setText(text)
        for col, label in enumerate(horizontalLabels):
            item = QTableWidgetItem(getValueIndocx(label, text))
            tableWidget.setItem(row, col, item)

    
    # tableWidget.resizeRowsToContents()
    tableWidget.setWindowTitle('总计：' + str(len(verticalLabels)))
    tableWidget.showMaximized()
    # textEdit.show()

    sys.exit(app.exec_())
